package com.sensei.search.nodes;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.queryParser.QueryParser;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipelineCoverage;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

import proj.zoie.api.IndexReaderFactory;

import com.browseengine.bobo.api.BoboBrowser;
import com.browseengine.bobo.api.BoboIndexReader;
import com.browseengine.bobo.api.Browsable;
import com.browseengine.bobo.api.BrowseRequest;
import com.browseengine.bobo.api.BrowseResult;
import com.browseengine.bobo.api.MultiBoboBrowser;
import com.browseengine.bobo.protobuf.BrowseProtobufConverter;
import com.browseengine.bobo.protobuf.BrowseRequestBPO;
import com.google.protobuf.TextFormat;

@ChannelPipelineCoverage("all")
public class SenseiServerHandler extends SimpleChannelUpstreamHandler {
  private static final Logger logger = Logger.getLogger(SenseiServerHandler.class);
  private final QueryParser _qparser;
  private final IndexReaderFactory<BoboIndexReader> _idxReaderFactory;
  
  public SenseiServerHandler(QueryParser qparser,IndexReaderFactory<BoboIndexReader> idxReaderFactory){
	  _qparser = qparser;
	  _idxReaderFactory = idxReaderFactory;
  }
  
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
		throws Exception {
		logger.error("Unexpected exception from downstream.",e.getCause());
		e.getChannel().close();
  }

  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
		throws Exception {
	  BrowseRequestBPO.Request req = (BrowseRequestBPO.Request)e.getMessage();
	  String reqString = TextFormat.printToString(req);
	  reqString = reqString.replace('\r', ' ').replace('\n', ' ');
	  logger.info("received req: \n"+reqString);
	  BrowseRequest boboReq = BrowseProtobufConverter.convert(req,_qparser);
	  
	  List<BoboIndexReader> readerList = _idxReaderFactory.getIndexReaders();
	  
	  ArrayList<Browsable> browseList = new ArrayList<Browsable>(readerList.size());
	  for (BoboIndexReader reader : readerList){
	    browseList.add(new BoboBrowser(reader));
	  }
	  
	  MultiBoboBrowser browser = null;
	  
	  try{
		  browser = new MultiBoboBrowser(browseList.toArray(new Browsable[browseList.size()]));
		  BrowseResult res = browser.browse(boboReq);
		  e.getChannel().write(BrowseProtobufConverter.convert(res));
	  }
	  finally{
		 if (browser!=null){
			 try{
			   browser.close();
			 }
			 catch(IOException ioe){
				 logger.error(ioe.getMessage(),ioe);
			 }
		 }
	  }  
  }
}
